package cn.shengchao.controler.ai;

import cn.shengchao.controler.ai.request.CreateStudyPlanRequest;
import cn.shengchao.controler.ai.request.CreateStudyPlanRequest.StudyDay;
import cn.shengchao.controler.ai.request.UpdateStudyPlanRequest;
import cn.shengchao.controler.ai.response.ApiResponse;
import cn.shengchao.examstar.ai.application.dto.StudyDayDTO;
import cn.shengchao.examstar.ai.application.dto.StudyPlanListDTO;
import cn.shengchao.examstar.ai.application.dto.StudyPlanSummaryDTO;
import cn.shengchao.examstar.ai.application.service.AiStudyPlanService;
import cn.shengchao.examstar.ai.domain.repository.IAiChatFreeSunRepository;
import cn.shengchao.examstar.ai.domain.valueobject.SpecificationType;
import cn.shengchao.examstar.ai.domain.valueobject.UserId;
import cn.shengchao.examstar.ai.infrastructure.external.ai.service.res.StudyPlanDify;
import cn.shengchao.examstar.knowledge.acl.ports.repositories.IKnowledgePointRepository;
import cn.shengchao.examstar.knowledge.application.ExerciseApplicationService;
import cn.shengchao.examstar.knowledge.domain.entity.KnowledgePoint;
import cn.shengchao.examstar.rpc.knowledge.req.KnowledgeReq;
import cn.shengchao.util.helper.LoginHelper;
import com.alibaba.fastjson2.JSON;
import com.shengchao.examstar.rpc.question.api.IQuestionRpc;
import com.shengchao.examstar.rpc.question.resp.QuestionListResp;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import top.continew.starter.core.validation.CheckUtils;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.web.model.R;

import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * 学习计划控制器
 * 处理学习计划相关的HTTP请求
 */
@RestController
@Slf4j
@CrossOrigin("${project.cross-origin}")
@RequestMapping("/api/${project.version}/studyPlans")
@Tag(name = "学习计划", description = "AI学习计划相关接口")
public class StudyPlanController {

    private static final Logger logger = LoggerFactory.getLogger(StudyPlanController.class);

    @Autowired
    private AiStudyPlanService aiStudyPlanService;

    @Autowired
    private IKnowledgePointRepository iKnowledgePointRepository;

    @Autowired
    private IQuestionRpc iQuestionRpc;

    @Autowired
    private AiController aiController;
    @Autowired
    private IAiChatFreeSunRepository iAiChatFreeSunRepository;

    /**
     * 创建学习计划
     *
     * @param request 创建学习计划请求
     * @return 操作结果
     */
    @PostMapping
    @Operation(
            summary = "创建学习计划",
            description = "创建一个新的学习计划，包含类目、掌握程度、每日学习时长建议、学习时间范围、学习建议及学习日程列表"
    )
    public R createStudyPlan(@RequestBody @Valid CreateStudyPlanRequest request) {
        ValidationUtils.throwIf(request.getSpecificationType() == null, "类目ID不能为空");

        Long userId = LoginHelper.getUserId();
        logger.info("创建学习计划请求: userId={}, specificationType={}, degreeOfMasteryCode={}, " +
                        "dailyStudyHours={}, startTime={}, endTime={}",
                userId, request.getSpecificationType(), request.getDegreeOfMasteryCode(),
                request.getDailyStudyHours(), request.getStartTime(), request.getEndTime());

        List<StudyDayDTO> studyDays = null;
        if (request.getScheduleItems() != null && !request.getScheduleItems().isEmpty()) {
            logger.info("收到学习日程项数量: {}", request.getScheduleItems().size());

            // 转换为StudyDayDTO列表
            studyDays = request.getScheduleItems().stream()
                    .map(this::convertToStudyDayDTO)
                    .collect(Collectors.toList());

            logger.info("已转换学习日程项，第一项: 日期={}, 任务={}, 时长={}分钟",
                    studyDays.getFirst().getDate(),
                    studyDays.getFirst().getJobName(),
                    studyDays.getFirst().getStudyTimeMinutes());
        }

        aiStudyPlanService.createStudyPlan(
                request.getSpecificationType(),
                userId,
                request.getDegreeOfMasteryCode(),
                request.getDailyStudyHours(),
                request.getStartTime(),
                request.getEndTime(),
                request.getStudyAdvice(),
                studyDays
        );

        return R.ok();
    }

    /**
     * 将请求中的StudyDay转换为StudyDayDTO
     */
    private StudyDayDTO convertToStudyDayDTO(StudyDay studyDay) {
        if (studyDay == null) {
            return null;
        }

        return StudyDayDTO.builder()
                .date(studyDay.getDate())
                .jobName(studyDay.getJobName())
                .knowledgePointId(studyDay.getKnowledgePointId() != null ? String.valueOf(studyDay.getKnowledgePointId()) : null)
                .knowledgePoint(studyDay.getKnowledgePoint())
                .studyTimeMinutes(studyDay.getStudyTimeMinutes())
                .completed(studyDay.getCompleted())
                .build();
    }

    /**
     * 判断当前用户在指定类目下是否存在学习计划
     * @param specificationType 类目ID
     * @return 是否存在学习计划
     */
    @GetMapping("/user-exists")
    @Operation(
            summary = "判断当前用户在指定类目下是否存在学习计划",
            description = "根据类目ID查询当前登录用户是否已有学习计划"
    )
    public R existsUserStudyPlanBySpecificationType(@RequestParam Long specificationType) {
        ValidationUtils.throwIf(specificationType == null, "类目ID不能为空");

        Long userId = LoginHelper.getUserId();
        boolean exists = aiStudyPlanService.existsUserStudyPlanBySpecificationType(specificationType, userId);
        return R.ok(Map.of("exists", exists));
    }

    /**
     * 获取学习计划摘要信息
     * @param specificationType 类目ID
     * @return 学习计划摘要
     */
    @GetMapping("/summary")
    @Operation(
            summary = "获取学习计划摘要信息(首页)",
            description = "获取当前用户在指定类目下的学习计划摘要信息，包括掌握程度、学习进度、薄弱知识点等"
    )
    public ApiResponse<StudyPlanSummaryDTO> getStudyPlanSummary(@RequestParam Long specificationType) {
        ValidationUtils.throwIf(specificationType == null, "类目ID不能为空");

        Long userId = LoginHelper.getUserId();
        logger.info("获取学习计划摘要请求: userId={}, specificationType={}", userId, specificationType);

        StudyPlanSummaryDTO summary = aiStudyPlanService.getStudyPlanSummary(userId, specificationType);

        return ApiResponse.success(summary);
    }

    /**
     * 获取当前用户的所有学习计划列表
     * @return 学习计划列表，包含类目ID和类目名称
     */
    @GetMapping("/list")
    @Operation(
            summary = "获取所有学习计划列表",
            description = "获取当前用户的所有学习计划列表，包含类目ID和类目名称等信息"
    )
    public List<StudyPlanListDTO> getStudyPlanList() {
        Long userId = LoginHelper.getUserId();
        logger.info("获取学习计划列表请求: userId={}", userId);
        return aiStudyPlanService.getUserStudyPlanList(userId);
    }

    /**
     * 修正学习计划
     * @param request 修正学习计划请求
     * @return 操作结果
     */
    @PutMapping
    @Operation(
            summary = "修正学习计划",
            description = "修正学习计划的学习总结、知识点、学习计划和做题及答案信息"
    )
    @Transactional
    public ApiResponse<Boolean> updateStudyPlan(@RequestBody @Valid UpdateStudyPlanRequest request) throws IOException, ExecutionException, InterruptedException {
        Long userId = LoginHelper.getUserId();
        boolean exists = aiStudyPlanService.existsUserStudyPlanBySpecificationType(request.getSpecificationType(), userId);
        if (exists) {
            return ApiResponse.success();
        }
        CheckUtils.throwIf(aiController.getFreeSum().getValue() <= 0, "本月免费次数已用完!");
        iAiChatFreeSunRepository.doAi(LoginHelper.getUserId(), 1L);
        // 查询知识树叶子节点
        KnowledgeReq knowledgeReq = new KnowledgeReq();
        knowledgeReq.setSpecificationType(request.getSpecificationType());
        List<KnowledgePoint> knowledgePoints = iKnowledgePointRepository.getKnowledgePointByLeafList(knowledgeReq);
        // 将知识树JSON存入knowledge字段
        String knowledgeJson = JSON.toJSONString(knowledgePoints);
        List<QuestionListResp> questions = iQuestionRpc.getQuestionListByQuestionSetId(String.valueOf(request.getQuestionSetId()));
        if (questions == null) {
            return ApiResponse.badRequest("问题集不存在");
        }
        String question = JSON.toJSONString(questions);
        StudyPlanDify result = aiStudyPlanService.updateStudyPlan(
                userId,
                request.getLearningSummary(),
                knowledgeJson,
                request.getStudyPlan(),
                question
        );
        if (result != null) {
            // 将修正后的学习计划转换为创建请求，并创建新的学习计划
            CreateStudyPlanRequest createStudyPlanRequest = convertToCreateStudyPlanRequest(result);
            createStudyPlanRequest.setUserId(LoginHelper.getUserId());
            createStudyPlanRequest.setSpecificationType(request.getSpecificationType());
            this.createStudyPlan(createStudyPlanRequest);
        }
//        exerciseApplicationService.batchUpdateKnowledgePointMasteryByWorkflow(userId,question);
        return ApiResponse.success(result != null);
    }

    /**
     * 将StudyPlanDify对象转换为CreateStudyPlanRequest对象
     *
     * @param studyPlanDify Dify返回的学习计划对象
     * @return 创建学习计划请求对象
     */
    private CreateStudyPlanRequest convertToCreateStudyPlanRequest(StudyPlanDify studyPlanDify) {
        if (studyPlanDify == null) {
            return null;
        }

        CreateStudyPlanRequest request = new CreateStudyPlanRequest();

        // 复制基本属性
        request.setUserId(studyPlanDify.getUserId());
        request.setSpecificationType(studyPlanDify.getSpecificationType());
        request.setDegreeOfMasteryCode(studyPlanDify.getDegreeOfMasteryCode());
        request.setDailyStudyHours(studyPlanDify.getDailyStudyHours());
        request.setStartTime(studyPlanDify.getStartTime());
        request.setEndTime(studyPlanDify.getEndTime());
        request.setStudyAdvice(studyPlanDify.getStudyAdvice());

        // 转换学习日程列表
        if (studyPlanDify.getScheduleItems() != null && !studyPlanDify.getScheduleItems().isEmpty()) {
            List<CreateStudyPlanRequest.StudyDay> scheduleItems = studyPlanDify.getScheduleItems().stream()
                    .map(this::convertToStudyDay)
                    .collect(Collectors.toList());

            request.setScheduleItems(scheduleItems);
        }

        return request;
    }

    /**
     * 将StudyPlanDify.StudyDay转换为CreateStudyPlanRequest.StudyDay
     */
    private CreateStudyPlanRequest.StudyDay convertToStudyDay(StudyPlanDify.StudyDay studyDay) {
        if (studyDay == null) {
            return null;
        }

        CreateStudyPlanRequest.StudyDay day = new CreateStudyPlanRequest.StudyDay();
        day.setDate(studyDay.getDate());
        day.setJobName(studyDay.getJobName());
        day.setKnowledgePointId(studyDay.getKnowledgePointId());
        day.setKnowledgePoint(studyDay.getKnowledgePoint());
        day.setStudyTimeMinutes(studyDay.getStudyTimeMinutes());
        day.setCompleted(studyDay.getCompleted());

        return day;
    }
}